package cn.net.yugu.doraemon.api.common.vo;

import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import cn.net.yugu.doraemon.api.common.model.VO;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author xiangzr
 * @version 2020/11/12 17:03:11
 */
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class PageResultVO<T> implements VO {

    private static final long serialVersionUID = 1053608201309756500L;

    private Integer pageNo;

    private Integer limit;

    private Long total;

    private List<T> data;
    private Integer currentCount;

    public static <R, T> PageResultVO<R> submit(Supplier<Long> countFunc,
                                                Supplier<List<T>> listFunc,
                                                PageQueryVO pageQueryVO) {
        return submit(countFunc, listFunc, pageQueryVO, null);
    }

    /**
     * @param countFunc       查询数量函数
     * @param listFunc        查询列表函数
     * @param pageQueryVO     分页
     * @param resultConverter 结果转换函数
     * @param <T>             分页对象
     * @return
     */
    public static <R, T> PageResultVO<R> submit(Supplier<Long> countFunc,
                                                Supplier<List<T>> listFunc,
                                                PageQueryVO pageQueryVO,
                                                Function<T, R> resultConverter
    ) {
        Long count = countFunc.get();
        if (count == 0) {
            PageResultVO<R> page = PageResultVO.<R>builder()
                    .total(count)
                    .pageNo(pageQueryVO.getPageNo())
                    .limit(pageQueryVO.getLimit())
                    .currentCount(0)
                    .build();
            return page;
        }
        resultConverter = resultConverter == null ? t -> (R) t : resultConverter;
        List<T> dataList = listFunc.get();
        List<R> resultDataList = dataList.stream()
                .map(resultConverter)
                .collect(Collectors.toList());
        PageResultVO<R> page = PageResultVO.<R>builder()
                .total(count)
                .pageNo(pageQueryVO.getPageNo())
                .limit(pageQueryVO.getLimit())
                .currentCount(resultDataList.size())
                .data(resultDataList)
                .build();
        return page;
    }
}
